package cn.ac.iie.ban.data.exchange.runner.tokenBucket.server;

import cn.ac.iie.ban.data.exchange.runner.tokenBucket.exception.DEFCInitException;
import cn.ac.iie.ban.data.exchange.runner.tokenBucket.util.PairList;
import cn.ac.iie.ban.data.exchange.runner.tokenBucket.util.ServiceInfo;
import cn.ac.iie.di.commons.httpserver.framework.handler.HandlerI;
import java.io.IOException;
import java.util.Collection;
import java.util.Map;
import javax.servlet.http.HttpServletRequest;
import javax.servlet.http.HttpServletResponse;
import org.apache.log4j.Logger;
import org.eclipse.jetty.server.Request;

public class GetTokenHandler implements HandlerI {

    private static final Logger LOGGER = Logger.getLogger(GetTokenHandler.class.getName());

    private static boolean active = false;

    private static SpeedLimitHelper helper = null;

    public static void initSpeedLimitHelper(Collection<String> metaUrls, String metaSuffix, int totalSpeed, int eachSpeed)
            throws DEFCInitException {
        GetTokenHandler.helper = new SpeedLimitHelper(new ServiceInfo(metaUrls, metaSuffix), totalSpeed, eachSpeed);
    }

    public static void initSpeedLimitHelper(ServiceInfo metaService, long updateIntervalSec,
            int totalSpeed,
            PairList<Integer, Integer> speedList,
            PairList<Integer, Integer> dataSizeLimit) throws DEFCInitException {
        GetTokenHandler.helper = new SpeedLimitHelper(metaService, updateIntervalSec, totalSpeed, speedList, dataSizeLimit);
    }

    public static void initSpeedLimitHelper(ServiceInfo metaService, long updateIntervalSec,
            int totalSpeed,
            PairList<Integer, Integer> speedList,
            PairList<Integer, Integer> dataSizeLimit,
            Map<String, Integer> specificLimitMap) throws DEFCInitException {
        GetTokenHandler.helper = new SpeedLimitHelper(metaService, updateIntervalSec, totalSpeed, speedList, dataSizeLimit, specificLimitMap);
    }

    public static void initSpeedLimitHelper(Collection< String> metaUrls, String metaSuffix, int totalSpeed, int eachSpeed, long updateIntervalSec)
            throws DEFCInitException {
        GetTokenHandler.helper = new SpeedLimitHelper(new ServiceInfo(metaUrls, metaSuffix), updateIntervalSec, totalSpeed, eachSpeed);
    }

    public static void initStatistic(String rmqNamesrv, String rmqTopic, int intevalSec) throws Exception {
        if (helper == null) {
            throw new Exception("please init speed limit helper first.");
        }
        helper.initStatistic(rmqNamesrv, rmqTopic, intevalSec);
    }

    @Override
    public void init() throws Exception {
        if (helper == null) {
            throw new Exception("speed limit helper not inited.");
        }
        helper.start();
        active = true;
    }

    public static void stop() {
        active = false;
        helper.stop();
    }

    @Override
    public void execute(Request pRequest, HttpServletRequest request, HttpServletResponse response) {

        //active
        if (!active) {
            response.setStatus(HttpServletResponse.SC_FORBIDDEN);
            return;
        }
        try {
            String res = null;

            String uid = request.getParameter("uid");
            String sizeStr = request.getParameter("size");
            int size = 0;
            String waitStr = request.getParameter("wait");
            boolean wait = false;

            LOGGER.debug("get request : uid=" + uid + ", size=" + size + ", wait=" + wait);

            if (null == uid || (uid = uid.trim()).isEmpty()) {
                response.sendError(HttpServletResponse.SC_BAD_REQUEST, "uid does not exist");
                LOGGER.warn("uid does not exist");
                return;
            }
            try {
                if (sizeStr == null || (sizeStr = sizeStr.trim()).isEmpty()) {
                    response.sendError(HttpServletResponse.SC_BAD_REQUEST, "size does not exist");
                    LOGGER.warn("size does not exist");
                    return;
                }
                size = Integer.valueOf(request.getParameter("size"));
            } catch (Exception e) {
                response.sendError(HttpServletResponse.SC_BAD_REQUEST, "size parsing error");
                LOGGER.warn("size parsing error");
                return;
            }

            if (null == waitStr) {
                response.sendError(HttpServletResponse.SC_BAD_REQUEST, "wait does not exist");
                LOGGER.warn("wait does not exist");
                return;
            } else if ("true".equals(waitStr.trim().toLowerCase())) {
                wait = true;
            } else {
                wait = false;
            }

            boolean ifGet;

            if (wait) {
                ifGet = helper.get(uid, size);
            } else {
                ifGet = helper.tryGet(uid, size);
            }
            LOGGER.debug("token result:" + ifGet);

//        long getAfter = tokenBucket.getCount();
            res = String.valueOf(ifGet);
//
//        logger.info("recive:id:" + id + "...size:" + size + "...wait:" + wait + "...countBefor:" + getBefor + "...countAfter:" + getAfter + "...response:" + res);
            response.getWriter().write(res);
            response.setStatus(HttpServletResponse.SC_OK);

//        activeThreadNum.decrementAndGet();
        } catch (Throwable t) {
            LOGGER.error("unknown exception occur.", t);
            try {
                response.sendError(HttpServletResponse.SC_INTERNAL_SERVER_ERROR, "unknown exception occur." + t.getMessage());
            } catch (IOException ex) {
            }
        }
    }

}
